/**
 * Hackystat 8 Hackerrific Twitter client.
 */
package org.hackystat.ui.hackerrific.client;

import java.util.ArrayList;

import org.gwtwidgets.client.wrap.Effect;
import org.gwtwidgets.client.wrap.EffectOption;

import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * This Panel class represents a tweet.
 * @author David J. Nickles
 *
 */
public class StatusPanel extends Composite implements ClickListener {
  
  private HorizontalPanel mainPanel;
  private FlowPanel animatorPanel;
  
  private Image avatarImage;
  private Image twitterpageImage;
  private Image homepageImage;
  private Image favoriteImage;
  private Label usernameLabel;
  private Label commentLabel;
  
  private String createdAt;
  private String tweetId;
  private String text;
  private String source;
  private String user;
  private String userId;
  private String userScreenName;
  private String userLocation;
  private String userDescription;
  private String userProfileImageUrl;
  private String userUrl;

  private String twitterUrl;

  /** {@literal} WAIT_IMAGE icon. */        
  public static final String WAIT_IMAGE = "images/wait-animated.gif"; 
  /** {@literal} USER_INVALID user invalid event state. */        
  private static final String USER_INVALID = "images/user-warning.gif"; 
  /** {@literal} USERTWITTERPAGEIMAGE go user twitter page function icon. */        
  private static final String USERTWITTERPAGEIMAGE = "images/tweet.gif"; 
  /** {@literal} USERHOMEPAGEIMAGE go homepage function icon. */        
  private static final String USERHOMEPAGEIMAGE = "images/web.gif"; 
  /** {@literal} FAVORITEIMAGE make a favorite tweet function icon. */  
  private static final String FAVORITEIMAGE = "images/favorite.gif";  
  /** {@literal} NEWPAGE directive to open page ina new browser window. */  
  private static final String NEWPAGE = "_blank";  
  /** {@literal} PAGEFEATURES features of new browser window. */  
  private static final String PAGEFEATURES = "";  
  /** {@literal} SMALLLABELSTYLE stylesheet class for labels. */  
  private static final String SMALLLABELSTYLE = "gwt-Label-small";   
  /** {@literal} EXAMPLELABELSTYLE stylesheet class for examples. */  
  private static final String EXAMPLELABELSTYLE = "gwt-Label-example";  
  /** {@literal} USERNAME stylesheet class for examples. */  
  private static final String USERNAME = "username";  
  /** {@literal} TWEETTEXT stylesheet class for examples. */  
  private static final String TWEETTEXT = "tweet"; 
  /** {@literal} FNSTRIPSTYLE stylesheet class for examples. */  
  private static final String FNSTRIPSTYLE = "fnstrip"; 
  /** {@literal} AVATAR stylesheet class for examples. */  
  private static final String AVATAR = "avatar"; 
  /** {@literal} PRCERRORNAME name for RPC errors. */  
  private static final String PRCERRORNAME = "Error on createFavorite RPC"; 

  
  /**
   * Applies a Scriptaculous effect to an element.
   * @param element The element to reveal
   * @param effect The effect to apply
   * 
   * Usage: applyEffectMac(getWidget(3).getElement(), "BlindUp");
   */
  public native void applyEffect(Element element, String effect) /*-{
    var ne = $wnd._nativeExtensions;
    $wnd._nativeExtensions = false;
    $wnd.Effect[effect](element);
    $wnd._nativeExtensions = ne;
  }-*/;   
  
  /**
   * Create and display a status panel.
   */
  private void draw() {

    this.mainPanel = new HorizontalPanel();
    this.animatorPanel = new FlowPanel();
    
    mainPanel.add(this.avatarImage = new Image(this.userProfileImageUrl));
    this.avatarImage.setStyleName(AVATAR);
    this.avatarImage.setTitle(this.userLocation);
    VerticalPanel list = new VerticalPanel();
    list.add(this.usernameLabel = new Label(this.userScreenName));
    this.usernameLabel.setStyleName(SMALLLABELSTYLE);
    this.usernameLabel.setTitle(this.userDescription);
    list.add(this.commentLabel = new Label(this.text));
    this.commentLabel.setStyleName(TWEETTEXT);
    mainPanel.add(list);
    VerticalPanel fnStrip = new VerticalPanel();
    fnStrip.add(this.twitterpageImage = new Image(USERTWITTERPAGEIMAGE));
    this.twitterpageImage.setPixelSize(20, 20);
    this.twitterpageImage.addClickListener(this);
    this.twitterpageImage.setTitle(this.twitterUrl);
    if (this.userUrl.length() > 0) {
      fnStrip.add(this.homepageImage = new Image(USERHOMEPAGEIMAGE));
      this.homepageImage.setPixelSize(20, 20);
      this.homepageImage.addClickListener(this);
      this.homepageImage.setTitle(this.userUrl);
    }
    fnStrip.add(this.favoriteImage = new Image(FAVORITEIMAGE));
    this.favoriteImage.setPixelSize(20, 20);
    this.favoriteImage.addClickListener(this);
    this.favoriteImage.setTitle("Make this tweet a favorite.");
    fnStrip.addStyleName(FNSTRIPSTYLE);
    mainPanel.add(fnStrip);
    
    this.animatorPanel.add(this.mainPanel);
    
    initWidget(this.animatorPanel);
  }

  /**
   * This method constructs and initializes a StatusPanel from an ArrayList of Strings
   * delivered from the servlet. 
   * @param rawStatus an ArrayList of strings delivered from the servlet.
   * index 0: XMLFormatDate of CreatedAt
   * index 1: String of Tweet Id
   * index 2: String of Text
   * index 3: String of Source
   * index 4: String of User
   * index 5: String of User Id
   * index 6: String of User Screen Name
   * index 7: String of User Location
   * index 8: String of User Description
   * index 9: String of User ProfileImageUrl
   * index 10: String of User Url
   * 
   * @gwt.typeArgs rawStatus <java.lang.String>
   */
  public StatusPanel(ArrayList rawStatus) {
    this.createdAt = (String) rawStatus.get(0);
    this.tweetId = (String) rawStatus.get(1);
    this.text = (String) rawStatus.get(2);
    this.source = (String) rawStatus.get(3);
    this.user = (String) rawStatus.get(4);
    this.twitterUrl = "http://twitter.com/" + this.user;
    this.userId = (String) rawStatus.get(5);
    this.userScreenName = (String) rawStatus.get(6);
    this.userLocation = (String) rawStatus.get(7);
    this.userDescription = (String) rawStatus.get(8);
    this.userProfileImageUrl = (String) rawStatus.get(9);
    this.userUrl = (String) rawStatus.get(10);
    draw();
  }

  /**
   * This method handles the response from the RPC call.
   * @param result the success of the RPC call.
   */
  public void handleCreateFavoriteResult(Boolean result) {
    this.favoriteImage.setUrl(FAVORITEIMAGE);
  }

  /**
   * Makes this tweet a favorite.
   * @param user user to authentication.
   * @param password user password for authentication.
   * @param tweetId user password for authentication.
   */
  private void rpcCreateFavorite(String user, String password, String tweetId) {
    this.favoriteImage.setUrl(WAIT_IMAGE);
    RPCServiceFactory.getInstance().getService().createFavorite(user, password, tweetId,
      new AsyncCallback()
      {
        public void onSuccess(Object result) {
          handleCreateFavoriteResult((Boolean) result);
        }

        public void onFailure(Throwable caught) {
          if (caught instanceof com.google.gwt.user.client.rpc.InvocationException) {
            log(PRCERRORNAME, "Cannot invoke method on servlet.");
          } 
          else {
            log(PRCERRORNAME, caught.toString());
          }
        }
      });
  }

  /**
   * This method responds to clicks on the function strip.
   * @param sender widget that was clicked on.
   * @see com.google.gwt.user.client.ui.ClickListener#onClick(com.google.gwt.user.client.ui.Widget)
   */
  public void onClick(Widget sender) {
    //Effect.fade(this.animatorPanel);
    if (sender.equals(this.twitterpageImage)) {
      // open new page with twitter user page address
      Window.open(this.twitterUrl, NEWPAGE, PAGEFEATURES);
    } 
    else if (sender.equals(this.homepageImage)) {
      // open new page with user home page address
      Window.open(this.userUrl, NEWPAGE, PAGEFEATURES);
    }
    else if (sender.equals(this.favoriteImage)) {
      // make this tweet a favorite tweet
      rpcCreateFavorite(Cookies.getCookie("user"), Cookies.getCookie("password"), this.tweetId);
    }
  }
  
  /**
   * Log this message in the display.
   * @param header the message header or subject
   * @param body the message body
   */
  public void log(String header, String body) {
    this.avatarImage.setUrl(USER_INVALID);
    this.usernameLabel.setText(header);
    this.commentLabel.setText(body);
  }
}
